package com.module.base.ext

import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import com.module.base.base.BaseExceptionViewModel
import com.module.base.network.exception.ServerException
import com.module.base.utils.LogUtils
import kotlinx.coroutines.*
import okhttp3.ResponseBody
import java.io.BufferedInputStream
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream

/**
 * activity使用的下载
 */
fun AppCompatActivity.download(
    path: String,
    block: suspend () -> ResponseBody,
    process: (Float) -> Unit,//进度
    success: (String) -> Unit,//成功回调
    failResult: (ServerException) -> Unit,
): Job {
    return download(lifecycleScope, path, block, process, success, failResult)
}

/**
 * Fragment使用的下载
 */
fun Fragment.download(
    path: String,
    block: suspend () -> ResponseBody,
    process: (Float) -> Unit,//进度
    success: (String) -> Unit,//成功回调
    failResult: (ServerException) -> Unit,
): Job {
    return download(lifecycleScope, path, block, process, success, failResult)
}

/**
 *  ViewModel 使用的下载
 */
fun BaseExceptionViewModel.download(
    path: String,
    block: suspend () -> ResponseBody,
    process: (Float) -> Unit,//进度
    success: (String) -> Unit,//成功回调
    failResult: (ServerException) -> Unit,
): Job {
    return download(viewModelScope, path, block, process, success, failResult)
}

/**
 *  ViewModel 使用的下载
 */
fun Any.download(
    path: String,
    block: suspend () -> ResponseBody,
    process: (Float) -> Unit,//进度
    success: (String) -> Unit,//成功回调
    failResult: (ServerException) -> Unit,
): Job {
    return download(GlobalScope, path, block, process, success, failResult)
}

/**
 * 下载文件
 * @param path 保存路径
 * @param block 请求体
 * @param process 进度回调
 * @param success 完成
 * @param failResult 失败
 */
private fun download(
    scope: CoroutineScope,
    path: String,
    block: suspend () -> ResponseBody,
    process: (Float) -> Unit,//进度
    success: (String) -> Unit,//成功回调
    failResult: (ServerException) -> Unit,
): Job {
    return scope.launch(Dispatchers.Main) {
        try {
            checkPath(path)
            //请求体
            var body : ResponseBody = block()
            //成功处理
            try {
                withContext(Dispatchers.IO) {
                    val contentLength = body.contentLength()
                    val inputStream = body.byteStream()
                    val file = File(path)
                    val outputStream = FileOutputStream(file)
                    var currentLength = 0
                    val bufferSize = 1024 * 8
                    val buffer = ByteArray(bufferSize)
                    val bufferedInputStream = BufferedInputStream(inputStream, bufferSize)
                    var readLength: Int
                    while (bufferedInputStream.read(buffer, 0, bufferSize)
                            .also { readLength = it } != -1
                    ) {
                        outputStream.write(buffer, 0, readLength)
                        currentLength += readLength
                        //当前进度回调用
                        withContext(Dispatchers.Main) {
                            process(currentLength.toFloat() / contentLength.toFloat() * 100)
                        }
                    }
                    bufferedInputStream.close()
                    outputStream.close()
                    inputStream.close()
                }
                //成功回调
                success(path)
            } catch (e: Exception) {
                LogUtils.e(e.message)
                //处理异常
                isDealException(null, e)?.apply {
                    failResult(this)
                }
            }
        } catch (it: Exception) {
            //处理异常
            isDealException(null, it)?.apply {
                failResult(this)
            }
        }
    }

}

/**
 * 检查路径
 */
private suspend fun checkPath(path: String): Boolean {
    return withContext(Dispatchers.IO) {
        check(!path.isNullOrEmpty()) { "文件路径不存在" }
        val file: File = File(path)
        val folder = file.parentFile
        if (!folder.exists()) {
            try {
                val isMkdirs = folder.mkdirs()
                if (!isMkdirs) {
                    throw FileNotFoundException("java.io.FileNotFoundException: $folder: open failed: ENOENT (No such file or directory)")
                }
            } catch (var17: Exception) {
                throw IllegalStateException("文件创建失败")
            }
        }
        return@withContext true
    }
}

fun isMainThread(): Boolean {

    return Looper.getMainLooper() == Looper.myLooper()
}
